#include "stdafx.h"
#include "RuleModel.h"

using namespace tinyxml2;

std::string CRuleModel::s_ServerURL;

int	CRuleModel::s_division = 0;
int	CRuleModel::s_division_capacity = 0;

CRuleModel*	CRuleModel::s_pInstance = nullptr;
CRuleModel*	CRuleModel::GetInstance()
{
	if( CRuleModel::s_pInstance == nullptr )
	{
		CRuleModel::s_pInstance = new CRuleModel;
	}

	return CRuleModel::s_pInstance;
}

CRuleModel::CRuleModel(void)
{
}

CRuleModel::~CRuleModel(void)
{
}

bool CRuleModel::Initialize()
{
	tinyxml2::XMLDocument doc;

	tinyxml2::XMLError error = doc.LoadFile("../BIN/config.xml");
	if( error != tinyxml2::XMLError::XML_SUCCESS )
		return false;

	tinyxml2::XMLNode* child = doc.FirstChild();
	if( child == nullptr )
		return false;

	XMLNode* node = child->NextSibling();
	if( node == nullptr || strcmp(node->Value(),"Info") != 0 )
		return false;

	ParseEnvironmentInformation( node );

	node = node->NextSibling();
	if( node == nullptr || strcmp(node->Value(), "ActionRule") != 0 )
		return false;

	ParseActionRules( node );

	node = node->NextSibling();
	if( node == nullptr || strcmp(node->Value(), "SessionRule") != 0 )
		return false;

	ParseSessionBehaviors( node );

	return true;
}

bool CRuleModel::ParseEnvironmentInformation( tinyxml2::XMLNode*& info )
{
	info = info->FirstChild();
	if (info == nullptr || strcmp(info->Value(),"ServerInfo") != 0 )
        return false;

	XMLElement* element = info->ToElement();
	const char* serverAddress = element->Attribute("address");
	const char* port = element->Attribute("port");

	CRuleModel::s_ServerURL = serverAddress;
	//CRuleModel::s_ServerURL += ":";
	//CRuleModel::s_ServerURL += port;

	info = info->NextSibling();
	if( info == nullptr || strcmp(info->Value(), "SessionInfo") != 0 )
		return false;

	XMLElement* attrubute = info->ToElement();
	CRuleModel::s_division = attrubute->IntAttribute("Division");
	CRuleModel::s_division_capacity = attrubute->IntAttribute("DivisionCapacity");

	for( XMLNode* group = info->FirstChild() ; group != nullptr ; group = group->NextSibling() )
	{
		auto element = group->ToElement();

		int id = element->IntAttribute("ID");
		int session_count = element->IntAttribute("Count");

		m_mapSessionInfo.insert( MAP_SESSION_INFOS::value_type(id,session_count) );
	}

    return true;
}

bool CRuleModel::ParseActionRules( tinyxml2::XMLNode*& node )
{
	if( node == nullptr || strcmp(node->Value(),"ActionRule") != 0 )
		return false;

	for( XMLNode* actions = node->FirstChild() ; actions != nullptr ; actions = actions->NextSibling() )
	{
		if( strcmp(actions->Value(), "Actions") != 0 )
			return false;

		XMLElement* element = actions->ToElement();

		Actions* actionGroup = new Actions;
		actionGroup->m_id = element->IntAttribute("ID");
		actionGroup->m_loop = element->IntAttribute("loop");
		actionGroup->m_interval = element->IntAttribute("interval");

		for( XMLNode* action = actions->FirstChild() ; action != nullptr ; action = action->NextSibling() )
		{
			element = action->ToElement();

			Action* instance = new Action;
			instance->m_actionName = element->Attribute("name");
			instance->m_interval = element->IntAttribute("interval");
			instance->m_loop = element->IntAttribute("loop");

			actionGroup->m_Actions.push_back( instance );
		}
		
		m_ActionRules.insert( MAP_ACTIONS::value_type(actionGroup->m_id,actionGroup) );
	}

	return true;
}

bool CRuleModel::ParseSessionBehaviors( tinyxml2::XMLNode*& node )
{
	if( node == nullptr || strcmp(node->Value(),"SessionRule") != 0 )
        return false;

	for( XMLNode* rule = node->FirstChild() ; rule != nullptr ; rule = rule->NextSibling() )
	{
		if( strcmp(rule->Value(), "Rule") != 0 )
			return false;

		XMLElement* element = rule->ToElement();

		unsigned long groupID = element->IntAttribute("GroupID");
		unsigned long actionID = element->IntAttribute("Action");

		Actions* actions = GetActionRule( actionID );
		if( actions == nullptr )
			return false;

		m_groupActions.insert( MAP_ACTIONS::value_type(groupID,actions) );
	} 

	return true;
}

size_t CRuleModel::GetSessionGroup( MAP_SESSION_INFOS::iterator& it )
{
	it = this->m_mapSessionInfo.begin();
	return m_mapSessionInfo.size();
}

Actions* CRuleModel::GetActionRule( unsigned long id )
{
	auto it = m_ActionRules.find( id );
	if( it == m_ActionRules.end() )
		return nullptr;

	return it->second;
}

Actions* CRuleModel::GetSessionGroupRule( unsigned long id )
{
	auto it = m_groupActions.find( id );
	if( it == m_groupActions.end() )
		return nullptr;

	return it->second;
}